// TrayIcon.cpp : implementation file
//

#include "stdafx.h"
#include "TrayIcon.h"


// CTrayIcon

IMPLEMENT_DYNAMIC(CTrayIcon, CWnd)
CTrayIcon::CTrayIcon(	MouseMsgHandlerPtr *pMouseMsgHandler, 
						unsigned int uHandlersCount, 
						CIconData *pIconData)
{
	CTrayIcon::Initialize(NULL, ::RegisterWindowMessage(_T("NotifyIcon")), pMouseMsgHandler, uHandlersCount, pIconData);
}

CTrayIcon::CTrayIcon(	CWnd* pWnd,
						unsigned int uNotificationMsg,
						MouseMsgHandlerPtr *pMouseMsgHandler, 
						unsigned int uHandlersCount, 
						CIconData *pIconData)
{
	CTrayIcon::Initialize(pWnd, uNotificationMsg, pMouseMsgHandler, uHandlersCount, pIconData);
}

void CTrayIcon::Initialize(	CWnd* pWnd,
							unsigned int uNotificationMsg,
							MouseMsgHandlerPtr *pMouseMsgHandler, 
							unsigned int uHandlersCount, 
							CIconData *pIconData)
{
	// Create an invisible window for the Tray Icon
    CTrayIcon::CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,0,0, NULL, 0);

	m_tNotifyIconData.cbSize = sizeof(NOTIFYICONDATA);

	SetTargetWnd(pWnd);
	SetNotificationMsg(uNotificationMsg);
	SetIconData(pIconData);	
	SetMouseMsgHandler(pMouseMsgHandler, uHandlersCount);
	m_bHiddenIcon = TRUE;

	m_tNotifyIconData.uFlags |= NIF_ICON;
	m_tNotifyIconData.hIcon = m_pIconData->GetIconHandler();
	m_tNotifyIconData.uID = m_pIconData->GetIconID();
	m_tNotifyIconData.uFlags |= NIF_TIP;
	if(m_pIconData->GetToolTip() != NULL)
		lstrcpyn(m_tNotifyIconData.szTip, m_pIconData->GetToolTip(), sizeof(m_tNotifyIconData.szTip)); 
	else 
		m_tNotifyIconData.szTip[0] = '\0';	
}

CTrayIcon::~CTrayIcon()
{
	ShowWindow(SW_HIDE);

	if(m_uTimer != 0)
		KillTimer(m_uTimer);

	if(m_uHoverTimer != 0)
		KillTimer(m_uHoverTimer);

	DeleteIcon();

	if(m_pIconData)
	{
		delete m_pIconData;
		m_pIconData = NULL; 
	}

	for( unsigned int i = 0; i < m_uHandlersCount; i++ )	    
		delete [] m_pMouseMsgHandler[i];

	delete [] m_pMouseMsgHandler;
}

void CTrayIcon::SetTargetWnd(CWnd* pWnd)
{
	if(pWnd != NULL)
		m_pWnd = pWnd;
	else
		m_pWnd = (CWnd*)this;

	m_tNotifyIconData.hWnd = m_pWnd->GetSafeHwnd(); 
}

void CTrayIcon::SetNotificationMsg(unsigned int uNotificationMsg)
{
	// Make sure we avoid conflict with other messages
    ASSERT(uNotificationMsg >= WM_APP);

	m_uNotificationMsg = uNotificationMsg;

	m_tNotifyIconData.uFlags |= NIF_MESSAGE;
	m_tNotifyIconData.uCallbackMessage = m_uNotificationMsg;
}

void CTrayIcon::SetMouseMsgHandler(MouseMsgHandlerPtr *pMouseMsgHandler, unsigned int uHandlersCount)
{
	m_pMouseMsgHandler = pMouseMsgHandler;
	m_uHandlersCount = uHandlersCount;
}

MouseMsgHandlerPtr* CTrayIcon::GetMouseMsgHandler() const
{
	return m_pMouseMsgHandler;
}

void CTrayIcon::SetIconData(IconDataPtr pIconData)
{
	m_pIconData = pIconData;
}

IconDataPtr CTrayIcon::GetIconData() const
{
	return m_pIconData;
}

BEGIN_MESSAGE_MAP(CTrayIcon, CWnd)
	ON_REGISTERED_MESSAGE(WM_TI_TASKBARCREATED, OnTaskBarCreated)
END_MESSAGE_MAP()

// CTrayIcon message handlers

LRESULT CTrayIcon::OnTaskBarCreated(WPARAM wParam, LPARAM lParam)
{
	VERIFY(AddIcon());
    return 0;
}

LRESULT CTrayIcon::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
	unsigned int uID = (unsigned int) wParam; 
    unsigned int uMouseMsg = (unsigned int) lParam; 
 
	for(unsigned int i=0; i<m_uHandlersCount; i++)
		if ( (uMouseMsg == m_pMouseMsgHandler[i]->GetMouseMsgID()) && (uID == m_pIconData->GetIconID()) )
			m_pMouseMsgHandler[i]->MouseMsgHandler();

	return 0;
}

LRESULT CTrayIcon::WindowProc(unsigned int msg, WPARAM wParam, LPARAM lParam) 
{
	if (msg == m_uNotificationMsg)
        return OnNotifyIcon(wParam, lParam);
	else if(msg == WM_TIMER)
		OnTimer(wParam);

	return CWnd::WindowProc(msg, wParam, lParam);
}

BOOL CTrayIcon::AddIcon()
{
	m_tNotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
 
    BOOL res = Shell_NotifyIcon(NIM_ADD, &m_tNotifyIconData); 
 
	//if (m_pIconData->GetIconHandler()) 
    //   DestroyIcon(m_pIconData->GetIconHandler()); 
 
	m_bHiddenIcon = FALSE;

    return res; 
}

BOOL CTrayIcon::DeleteIcon()
{	
	return Shell_NotifyIcon(NIM_DELETE, &m_tNotifyIconData);
}

BOOL CTrayIcon::HideIcon()
{
	if (m_bHiddenIcon)
        return TRUE;

	m_tNotifyIconData.uFlags = NIF_STATE;
    m_tNotifyIconData.dwState = NIS_HIDDEN;
    m_tNotifyIconData.dwStateMask = NIS_HIDDEN;
	BOOL res = m_bHiddenIcon = Shell_NotifyIcon( NIM_MODIFY, &m_tNotifyIconData);

	DeleteIcon();

	return res;
}

BOOL CTrayIcon::ShowIcon()
{
	if (!m_bHiddenIcon)
        return TRUE;

	m_tNotifyIconData.uFlags = NIF_STATE;
    m_tNotifyIconData.dwState = 0;
    m_tNotifyIconData.dwStateMask = NIS_HIDDEN;
    BOOL res = Shell_NotifyIcon ( NIM_MODIFY, &m_tNotifyIconData );
    m_bHiddenIcon = FALSE;

	AddIcon();

	return res;
}

BOOL CTrayIcon::RefreshIcon()
{
	if (m_bHiddenIcon)
        return TRUE;

	DeleteIcon();	

	m_tNotifyIconData.uFlags = NIF_STATE;
    m_tNotifyIconData.dwState = 0;
    m_tNotifyIconData.dwStateMask = NIS_HIDDEN;
    BOOL res = Shell_NotifyIcon ( NIM_MODIFY, &m_tNotifyIconData );
    m_bHiddenIcon = FALSE;

	AddIcon();

	return res;
}

